package com.opencloud.common.utils;


import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.springframework.util.Base64Utils;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

/**
 * @author ittahac
 * @description AES加密解密类
 */
public class AesUtil {
    private final int keySize = 128;
    private final int iterationCount = 147;
    private final Cipher cipher;
    private static String status = null;
    private static String passphase = null;
    public static String salt = null;

    public AesUtil() {
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw fail(e);
        }
    }

    public String encrypt(String salt, String iv, String passphrase, String plaintext) {
        try {
            SecretKey key = generateKey(salt, passphrase);
            byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, plaintext.getBytes("UTF-8"));
            return base64(encrypted);
        } catch (UnsupportedEncodingException e) {
            throw fail(e);
        }
    }

    public String decrypt(String salt, String iv, String passphrase, String ciphertext) {
        try {
            SecretKey key = generateKey(salt, passphrase);
            byte[] text=base64(ciphertext);
            byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, text);
            return new String(decrypted, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw fail(e);
        }
    }

    private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {
        try {
            cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));
            return cipher.doFinal(bytes);
        } catch (InvalidKeyException
                | InvalidAlgorithmParameterException
                | IllegalBlockSizeException
                | BadPaddingException e) {
            throw fail(e);
        }
    }

    private SecretKey generateKey(String salt, String passphrase) {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize);
            SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            return key;
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw fail(e);
        }
    }

    public static String random(int length) {
        byte[] salt = new byte[length];
        new SecureRandom().nextBytes(salt);
        return hex(salt);
    }

    public static String base64(byte[] bytes) {
        try {
            return Base64.encodeBase64String(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] base64(String str) {
        try {
            String str1=str.replaceAll(" ","");
            return Base64.decodeBase64(str1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String hex(byte[] bytes) {
        return new String(Hex.encodeHex(bytes));
    }

    public static byte[] hex(String str) {
        try {
            return Hex.decodeHex(str.toCharArray());
        } catch (DecoderException e) {
            throw new IllegalStateException(e);
        }
    }

    private IllegalStateException fail(Exception e) {
        return new IllegalStateException(e);
    }

    /**
     * @description 进行加密的方法
     * @param originText
     * @param iv
     * @return String 加密后的结果
     */
    public static String en(String originText,String iv) {
        if ("0".equals(status)) {
            return originText;
        }
        try {
            return new AesUtil().encrypt(salt,iv,passphase,originText);
        }catch (Exception e) {
            return "";
        }
    }

    /**
     * @description 进行解密的方法
     * @param aesText
     * @param iv
     * @return String 解密后的结果
     */
    public static String de(String aesText,String iv) {

        if ("0".equals(status)) {
            return aesText;
        }
        try {
            return new AesUtil().decrypt(salt,iv,passphase,aesText);
        }catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public static void main(String[] args) throws Exception {
        String salt = RandomValueUtils.uuid();
        String iv = AesUtil.random(16);
        String IV = "964f99fdb425af9a91f401750bc675fa"; //tyg
        String SALT = "d1d909d038bf481e9479f66677e0aad0";
        System.out.println("盐：");
        System.out.println(salt);
        System.out.println("iv：");
        System.out.println(iv);
        String PLAIN_TEXT = "12345678";
        //String PASSPHRASE = "<script>var tyg='zytang';var ganggang = 1; var zfq = '1234567890'</script>";
        String PASSPHRASE = "I5OCkMBFw4VbeUSDfTgfPyws";
        AesUtil util = new AesUtil();
        String encrypt = util.encrypt(SALT, IV, PASSPHRASE, PLAIN_TEXT);
        System.out.println(encrypt);


        System.out.println(Base64Utils.encode(encrypt.getBytes()));

        String decrypt = util.decrypt(SALT, IV, PASSPHRASE, encrypt);
        System.out.println(decrypt);
//        String data = util.encrypt(SALT,"40e6caa88cc44193b4be8030029f85bf",PASSPHRASE,PLAIN_TEXT);
//        System.out.println(data);
//        String str = URLDecoder.decode("O5zrbt4B2Y%2BN0LAfM%2F%2BpYlzFJqtALTavfkBTzZaygiSwl1tkCDUTNqylkS0986exmPl8e%2BJEEdUESiGtO4ScYQ%3D%3D", System.getProperty("encoding", "UTF-8"));
//        System.out.println(str);
//        System.out.println(util.decrypt(SALT,"40e6caa88cc44193b4be8030029f85bf",PASSPHRASE,"O5zrbt4B2Y+N0LAfM/+pYlzFJqtALTavfkBTzZaygiSwl1tkCDUTNqylkS0986exmPl8e+JEEdUESiGtO4ScYQ=="));
    }
}
